package com.magold.logic.magold;

import org.andengine.entity.scene.Scene;
import org.andengine.entity.shape.IAreaShape;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.extension.physics.box2d.util.constants.PhysicsConstants;
import org.andengine.opengl.texture.region.ITiledTextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.magold.algorithm.MagoldMath;
import com.magold.context.IContext;
import com.magold.logic.ISpriteLogic;
import com.magold.logic.LogicConstants;
import com.magold.logic.LogicPhysicsHelper;
import com.magold.logic.LogicSpriteWrapper;
import com.magold.physics.MagoldPhysicsConnector;
import com.magold.sprite.IMultiTextureSprite;
import com.magold.sprite.MultiTextureSprite;

public class LogicSupports extends ItemsSupports implements ISpriteLogic {
	public static class MagoldConstants extends LogicConstants {
		protected ITiledTextureRegion mTexture;
		protected ITiledTextureRegion mHalo;
		protected ITiledTextureRegion mFinishSprite;
		
		public MagoldConstants(IContext pActivity) {
			super(pActivity);
		}
	}
	
	protected static MagoldConstants sConstants;
	public static void customize(MagoldConstants pConstants) {
		sConstants = pConstants;
	}

	private static final FixtureDef sCircleFixture = PhysicsFactory.createFixtureDef(5.0f, 0.35f, 0.1f);
	private static final FixtureDef sRectFixture = PhysicsFactory.createFixtureDef(5.0f, 0.35f, 0.1f);
	protected static final float HEIGHT_SCALE = 0.2F;
	protected static final float WIDTH_SCALE = 1.2F;
	
// ==============================================================================
// =============================== NON STATIC ===================================
// ==============================================================================
	protected IMultiTextureSprite mSprite;
	protected IMultiTextureSprite mHalo;
	protected MagoldPhysicsConnector mConnector;
	protected Scene mScene;
	
	@Override
	public MagoldPhysicsConnector findPhysicsConnector(IAreaShape pShape) {
		if (pShape == mSprite) return mConnector;
		
		return null;
	}

	// ignore pRotation & pScale now. Maybe I will implement it.
	@Override
	public void createSceneData(float pX, float pY, float pRotation, float pScale, Scene pScene) {
		VertexBufferObjectManager vbom = sConstants.mContext.getVertexBufferObjectManager();
		mSprite = new MultiTextureSprite(pX, pY, 0, sConstants.mTexture, vbom);
		mSprite.put(1, sConstants.mFinishSprite);
		LogicSpriteWrapper.wrap(mSprite, pScale, sConstants, this, pRotation, pScene);
		
		mHalo = new MultiTextureSprite(-2, -2, 0, sConstants.mHalo, vbom);
		mHalo.setRotationCenter(mHalo.getWidth() / 2, mHalo.getHeight() / 2);
		mSprite.attachChild(mHalo);
		
		mScene = pScene;
	}

	@Override
	public void createPhysicsData(PhysicsWorld pWorld) {
		Body body = PhysicsFactory.createCircleBody(pWorld, mSprite, BodyType.DynamicBody, sCircleFixture);
		
		createRectFixture(body);
		
		body.setSleepingAllowed(false);
		body.setBullet(true);
		
		mConnector = LogicPhysicsHelper.connectBody(pWorld, body, mSprite);
	}

	private void createRectFixture(Body body) {
		PolygonShape boxPoly = new PolygonShape();
		
		float width = mSprite.getWidth() * WIDTH_SCALE / PIXEL_TO_METER_RATIO_DEFAULT;
		float height = mSprite.getHeight() * HEIGHT_SCALE / PIXEL_TO_METER_RATIO_DEFAULT;
		boxPoly.setAsBox(width/2, height/2);
		sRectFixture.shape = boxPoly;
		sRectFixture.isSensor = true;
		body.createFixture(sRectFixture);
		
		boxPoly.dispose();
	}

	@Override
	public boolean isStatic() {
		return false;
	}

	@Override
	public void startCollide(ISpriteLogic pAnthor, Contact pContact) {
	}

	@Override
	public void endCollide(ISpriteLogic pAnthor, Contact pContact) {
	}
	
	/**
	 * 
	 * @return speed in meter.
	 */
	public Vector2 getSpeedInMeter() {
		return mConnector.getBody().getLinearVelocity();
	}

	public IMultiTextureSprite getSprite() {
		return mSprite;
	}

	@Override
	public void addTempVelocity(Vector2 pValue) {
		MagoldMath.pixel2Meter(pValue);
		Body b = mConnector.getBody();
		pValue.mul(b.getMass());
		b.applyLinearImpulse(pValue, b.getWorldCenter());
	}

	@Override
	public Vector2 getTempVelocity() {
		if (mConnector == null) {
			return new Vector2();
		} else {
			Vector2 pixelVelocity = mConnector.getBody().getLinearVelocity();
			return pixelVelocity.mul(PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT);
		}
	}
	
	
	
}
